package safeCommitter.core.view.main;

import java.util.Iterator;

import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.IMenuListener;
import org.eclipse.jface.action.IMenuManager;
import org.eclipse.jface.action.IToolBarManager;
import org.eclipse.jface.action.MenuManager;
import org.eclipse.jface.action.Separator;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.CLabel;
import org.eclipse.swt.custom.SashForm;
import org.eclipse.swt.custom.ViewForm;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.ToolBar;
import org.eclipse.swt.widgets.Tree;
import org.eclipse.swt.widgets.TreeColumn;
import org.eclipse.ui.IActionBars;
import org.eclipse.ui.IWorkbenchActionConstants;
import org.eclipse.ui.part.ViewPart;

import safeCommitter.core.view.action.ShowFailuresAction;
import safeCommitter.core.view.action.ShowHistoryAction;
import safeCommitter.core.view.action.relaunch.DebugAction;
import safeCommitter.core.view.action.relaunch.RelaunchAction;
import safeCommitter.core.view.action.relaunch.RelaunchFailuresAction;
import safeCommitter.core.view.main.progress.CounterPanel;
import safeCommitter.core.view.main.progress.JUnitProgressBar;
import safeCommitter.core.view.main.sorter.SorterManager;
import safeCommitter.test.executor.common.TestResultType;
import safeCommitter.test.report.ISCClassMethodTestResult;
import safeCommitter.test.report.RootClazzResult;

public class SCReportView extends ViewPart {

	private TreeViewer viewer;

	private Action showFailures;
	private Action relaunchFailures;
	private RelaunchAction debugFailure;
	private Action showHistory;
	private final SorterManager sorterManager = new SorterManager();

	private Boolean screenIsShowingAllTests = true;

	private RootClazzResult base;

	private JUnitProgressBar junitProgressBar;

	private CounterPanel counterPanel;

	final Image fStackViewIcon = SCViewUtils
			.createImage("icons/stackframe.gif");

	@Override
	public void createPartControl(final Composite parent) {
		GridLayout gridLayout = new GridLayout();
		gridLayout.marginWidth = 0;
		gridLayout.marginHeight = 0;
		parent.setLayout(gridLayout);
		createProgressCountPanel(parent);
		SashForm form = new SashForm(parent, SWT.HORIZONTAL);
		form.setLayoutData(new GridData(GridData.FILL_BOTH));
		Tree tree = buildTree(form);
		buildColumns(tree);
		FailureTraceView failureView = buildStackTrace(form);
		form.setWeights(new int[] { 200, 200 });
		viewer = new TreeViewer(tree);
		sorterManager.addSorter(viewer, tree.getColumns());
		viewer.setLabelProvider(new SCLabelProvider());
		RootClazzResult root = new RootClazzResult();
		SCReportContentProvider reportContentProvider = new SCReportContentProvider(
				root, junitProgressBar, counterPanel, failureView);
		createToolBar(reportContentProvider);
		viewer.setContentProvider(reportContentProvider);
		viewer.setInput(root);
		createContextMenu(tree);
		base = root;
	}

	private Composite createProgressCountPanel(final Composite parent) {
		Display display = parent.getDisplay();

		Composite composite = new Composite(parent, SWT.NONE);
		GridLayout layout = new GridLayout();
		layout.numColumns = 2;
		composite.setLayout(layout);
		junitProgressBar = new JUnitProgressBar(composite);
		junitProgressBar.setLayoutData(new GridData(GridData.GRAB_HORIZONTAL
				| GridData.HORIZONTAL_ALIGN_FILL));

		counterPanel = new CounterPanel(composite);
		counterPanel.setLayoutData(new GridData(GridData.GRAB_HORIZONTAL
				| GridData.HORIZONTAL_ALIGN_FILL));

		composite.setLayoutData(new GridData(GridData.GRAB_HORIZONTAL
				| GridData.HORIZONTAL_ALIGN_FILL));
		return composite;
	}

	private FailureTraceView buildStackTrace(final SashForm form) {
		ViewForm stackTrace = new ViewForm(form, SWT.NONE);
		stackTrace.setLayout(new FillLayout());
		CLabel label = new CLabel(stackTrace, SWT.NONE);
		label.setText("Stack Trace");
		label.setImage(fStackViewIcon);
		stackTrace.setTopLeft(label);
		ToolBar failureToolBar = new ToolBar(stackTrace, SWT.FLAT | SWT.WRAP);
		stackTrace.setTopCenter(failureToolBar);
		FailureTraceView failureView = new FailureTraceView(stackTrace, this,
				failureToolBar);
		stackTrace.setContent(failureView.getComposite());
		return failureView;
	}

	private Tree buildTree(final SashForm parent) {
		final ViewForm sc = new ViewForm(parent, SWT.NONE);
		Tree tree = new Tree(sc, SWT.NONE);
		tree.setLinesVisible(false);
		tree.setHeaderVisible(true);
		sc.setContent(tree);
		return tree;
	}

	private void buildColumns(final Tree tree) {
		TreeColumn column = new TreeColumn(tree, SWT.NONE, 0);
		column.setText("Test");
		column.setWidth(180);
		column.setAlignment(SWT.LEFT);
		column = new TreeColumn(tree, SWT.NONE, 1);
		column.setText("Time Elapsed(ms)");
		column.setWidth(100);
		column.setAlignment(SWT.RIGHT);
		// column = new TreeColumn(tree, SWT.NONE, 2);
		// column.setText("Type");
		// column.setWidth(70);
		// column.setAlignment(SWT.RIGHT);
	}

	private void createToolBar(
			final SCReportContentProvider reportContentProvider) {
		IActionBars actionBars = getViewSite().getActionBars();
		IToolBarManager toolBar = actionBars.getToolBarManager();
		showFailures = new ShowFailuresAction(this);
		showHistory = new ShowHistoryAction(this);
		toolBar.add(showFailures);
		// toolBar.add(showHistory);
		relaunchFailures = new RelaunchFailuresAction(reportContentProvider);
		debugFailure = new DebugAction(reportContentProvider);
		actionBars.updateActionBars();
	}

	@Override
	public void setFocus() {
		viewer.getControl().setFocus();

	}

	public TreeViewer getViewer() {
		return viewer;
	}

	@SuppressWarnings("unchecked")
	public void switchBetweenAllAndFailures() throws CloneNotSupportedException {
		RootClazzResult input = (RootClazzResult) viewer.getInput();
		if (input.getChildren().isEmpty() && base.getChildren().isEmpty()) {
			return;
		}
		if (screenIsShowingAllTests) {
			base = (RootClazzResult) input.clone();
			for (Iterator iterator = input.getChildren().iterator(); iterator
					.hasNext();) {
				ISCClassMethodTestResult clazz = (ISCClassMethodTestResult) iterator
						.next();
				if (clazz.getStatus().equals(TestResultType.SUCCESS)) {
					iterator.remove();
				}
			}
			viewer.setInput(input);
		} else {
			viewer.setInput(base);
		}
		screenIsShowingAllTests = !screenIsShowingAllTests;
	}

	void setScreenIsShowingAllTests(final Boolean screenIsShowingAllTests) {
		this.screenIsShowingAllTests = screenIsShowingAllTests;
	}

	private void createContextMenu(final Tree tree) {
		MenuManager menuManager = new MenuManager();
		menuManager.setRemoveAllWhenShown(true);
		menuManager.addMenuListener(new IMenuListener() {
			public void menuAboutToShow(final IMenuManager manager) {
				fillContextMenu(manager);
			}
		});
		Menu menu = menuManager.createContextMenu(tree);
		tree.setMenu(menu);
	}

	void fillContextMenu(final IMenuManager menu) {
		menu.add(relaunchFailures);
		menu.add(debugFailure);
		menu.add(new Separator());
		menu.add(new Separator(IWorkbenchActionConstants.MB_ADDITIONS));
		menu
				.add(new Separator(IWorkbenchActionConstants.MB_ADDITIONS
						+ "-end"));
	}

}
